/**
 *
 */
define(function(){
    const PDSCONST = {
        PDS_MSGTYPE: 102,
        //PDS_EVT_CONNECTED: 10001,
        //PDS_EVT_DISCONNECTED: 10002,
        PDS_EVT_CONNECTED: 12,
        PDS_EVT_DISCONNECTED: 13,
        EVT_AGENTREGISTERSUCCESS: 80050,
        EVT_AGENTUNREGISTERSUCCESS: 80052,

        REQ_AGENTREGSITER: 80001,
        REQ_AGENTUNREGSITER: 80002,
        REQ_AGENTAVAILABLE: 80003,
        REQ_AGENTUNAVAILABLE: 80004,
        REQ_AGENTBUSY: 80005,
        REQ_AGENTCOMPLETECALL: 80006,
        REQ_AGENTGETALLACTIVECAMPAIGN: 80007,
        REQ_AGENTACW: 80008,
        REQ_AGENTDONOTCALL: 80009,
        REQ_AGENTOTHERWORK: 80010,
        REQ_AGENTRESCHEDULECALL: 80011

    };

    var _timer_keepalive_count = 0;
    var _timer_gap = 0;

    var extr = {};
    var Extra = function(project, params){
        extr.project = project;
        this.name = "ctiextra_elitepds";
        $SC.regcall(this.name, [["queryextra", this.queryCTICall]], params);
        $SC.addEvtListener(this.name, "OnSCTIEvent", OnSCTIEvent, -1, params);
    };

    Extra.prototype = {
        queryCTICall : function(callName, callParams, callback){
            if (callParams.callname) {
                if (callParams.callname.toLowerCase() == 'setpdsinfo') {
                    var params = userdata2jsonuserdata(callParams.params);
                    extr.campaignid0 = params.campaignid;
                    logmsg("campaignid = " + extr.campaignid0);
                    if ($SC.agentState > 1) {
                        extr.connectpdsproxy();
                    }
                } else if (callParams.callname.toLowerCase() == 'setpdsurl') {
                    var params = userdata2jsonuserdata(callParams.params);
                    extr.pdsurl0 = params.pdsurl;
                    logmsg("pdsurl = " + extr.pdsurl0);
                    if ($SC.agentState > 1) {
                        extr.connectpdsproxy();
                    }
                } else
                    if (callParams.callname.toLowerCase() == "setpdscompletioncode" || callParams.callname.toLowerCase() == "setcompletioncode") {
                    var params = userdata2jsonuserdata(callParams.params);
                    var completioncode = params.completioncode;
                    var nextcalltime = params.nextcalltime;
                    var phone = params.phone;
                    var objective_guid = params.objective_guid;
                    var obcallid = $SC.CallInfo.AttachData("obcallid") || objective_guid;
                    if (obcallid) {
                        switch (completioncode.toString()) {
                            case "4092":
                                //donotcall
                                extr.donotcall(obcallid);
                                break;
                            case "4093":
                                //reschedule
                                extr.reschedulecall(obcallid, phone, nextcalltime);
                                break;
                            default:
                                var datas = {};
                                addJsonStringValue(datas, "event_guid", $SC.CallInfo.Event_GUID);
                                extr.agentcompletecall(obcallid, completioncode, datas);
                        }
                    }
                }

            }
        }
    };

    Extra.keepalive = function()
    {
        var request = {
            //request: {type:1, value: 11111},
            request: {type:1, value: 0},
            event: {type:1, value: 0},
            recchannelid : {type:1, value: extr.channelid},
            thisdn: {type:3, value: extr.dn},
            projectid: {type: 3, value: extr.project.id}
        };
        _timer_keepalive_count++;
        //console.log('::ctiextra_eliterecord, keepalive', _timer_keepalive_count, _timer_gap);
        logmsg("keepalive", _timer_keepalive_count, _timer_gap);
        extr.websocket.send(JSON.stringify(request));
    }

    function logmsg()
    {
        var msg = "[ctiextra_elitepds]";
        for (let i=0; i<arguments.length; i++) {
            var s1 = arguments[i];
            if (typeof(s1) === "object") {
                if (s1.callee) {
                    var args = s1;
                    var msg1 = "";
                    for (let j=0; j<args.length; j++) {
                        s1 = args[j];
                        if (typeof(s1) === "object") {
                            s1 = JSON.stringify(s1);
                        }
                        if (j===0) {
                            msg1 = s1;
                        } else {
                            if ([" ", ",", ":"].indexOf(msg1.substr(msg1.length-1))>=0) {
                                msg1 = msg1 + s1;
                            } else {
                                msg1 = msg1 + "," + s1;
                            }
                        }
                    }
                    s1 = msg1;
                } else {
                    s1 = JSON.stringify(s1);
                }
            } else if (typeof(s1) === "function") {
                continue;
            }
            if (i===0) {
                msg = msg + s1;
            } else {
                if ([" ", ",", ":"].indexOf(msg.substr(msg.length-1))>=0) {
                    msg = msg + s1;
                } else {
                    msg = msg + "," + s1;
                }
            }
        }
        $SC.addconsolelog(msg);
    }

    function addJsonStringValue(jsonobj, name, value)
    {
        jsonobj[name.toLowerCase()] = {type: 3, value: value};
    }

    function addJsonIntValue(jsonobj, name, value)
    {
        jsonobj[name.toLowerCase()] = {type: 1, value: value};
    }

    function addJsonDateValue(jsonobj, name, value)
    {
        jsonobj[name.toLowerCase()] = {type: 4, value: value};
    }

    function addJsonDatasValue(jsonobj, name, value)
    {
        jsonobj[name.toLowerCase()] = {type: 5, value: value};
    }

    function userdata2jsonuserdata(userdatas) {
        //userdatas: JSON Object, JSON string, '|' and '=' splitted key-value string
        if (userdatas) {
            if (typeof (userdatas) == 'object') {
                return userdatas;
            }
            try {
                var t_datas = JSON.parse(userdatas);
                return t_datas;
            } catch (err) {
                var iudskeys = userdatas.toLowerCase().indexOf('|userdatakeys=');
                //var udskeys = [];
                if (iudskeys >= 0) {
                    //var u1 = userdatas.substr(iudskeys + '|userdatakeys='.length)
                    //udskeys = u1.split('|');
                    userdatas = userdatas.substr(0, iudskeys);
                }
                var t_data = {};
                var uud = '';
                var iuud = ('|' + userdatas.toLowerCase()).indexOf('|raw_data=');
                if (iuud >= 0) {
                    uud = userdatas.substr(iuud + '|raw_data='.length - 1);
                } else {
                    var iuud = ('|' + userdatas.toLowerCase()).indexOf('|rawdata=');
                    if (iuud >= 0) {
                        uud = userdatas.substr(iuud + '|rawdata='.length - 1);
                    } else {
                        iuud = ('|' + userdatas.toLowerCase()).indexOf('|uu_data=');
                        if (iuud >= 0) {
                            uud = userdatas.substr(iuud + '|uu_data='.length - 1);
                        }
                    }
                }
                if (iuud >= 0) {
                    userdatas = userdatas.substr(0, iuud - 1);
                }

                if (userdatas) {
                    var i = userdatas.lastIndexOf("=");
                    var s2 = userdatas;
                    if (i>0) {
                        s2 = s2.substr(i+2);
                        userdatas = userdatas.substr(0, i+2);
                    }
                    var t_data1 = userdatas.split("\|");
                    //for (let onedata in t_data1){
                    for (let i = 0; i < t_data1.length; i++) {
                        var onedata = t_data1[i];
                        var n = onedata.indexOf("=");
                        if (n >= 0) {
                            if (i=== t_data1.length-1) {
                                t_data[onedata.substr(0, n).toLowerCase()] = onedata.substr(n + 1) + s2;
                            } else {
                                t_data[onedata.substr(0, n).toLowerCase()] = onedata.substr(n + 1);
                            }
                        }
                    }
                }
                if (uud) {
                    t_data.uu_data = uud;
                }
                //return JSON.stringify(t_data);
                return t_data;
            }
        }
    };

    extr.connectpdsproxy = function(serverendpoint) {
        extr.pdsstatus = "";
        if (serverendpoint) {
            extr.serverendpoint = serverendpoint;
        } else if (extr.pdsurl0) {
            extr.serverendpoint = extr.pdsurl0;
        } else {
        //};
        //if (!extr.serverendpoint) {
            extr.serverendpoint = $SC._getconfig("PDS", "PDSURL");
        }
        extr.websocketclose();
        //$SC.addconsolelog('::ctiextra_elitepds: websocket ' + extr.serverendpoint);
        logmsg("websocket", extr.serverendpoint);
        extr.websocket = new WebSocket(extr.serverendpoint);
        extr.websocket.onopen = function (event) {
            _timer_keepalive_count = 0;
            extr.pdsstatus = "wsopen";
            //$SC.addconsolelog('::ctiextra_elitepds: socket connected');
            logmsg("socket connected");
            extr.socketconnected = true;

            if (extr.m_connect) {
                $SC.stopTimer("","","pdsreconnect");
                extr.m_connect = 0;
            }
            $SC.startTimer(30000, 0, 0, "pdskeepalive", function(counter, gap, time) {
                logmsg("keepalive ", counter,  gap, time);
                Extra.keepalive();
            });
        };
        extr.websocket.onclose = function (event) {
            extr.pdsstatus = "wsclose";
            //$SC.addconsolelog('::ctiextra_eliterecord: socket disconnected');
            logmsg("socket disconnected");
            extr.socketconnected = false;

            $SC.stopTimer("","","pdskeepalive");

            extr.reconnect();
        };

        extr.websocket.onmessage = function (event) {
            extr.OnPDSEvent(event);
        };
        extr.websocket.onerror = function (event) {
            //$SC.addconsolelog('::ctiextra_eliterecord: socket Error ' + JSON.stringify(event));
            logmsg("socket error", event);
        }
    };

    extr.reconnect = function() {
        if ($SC.agentState > 1) {
            logmsg('try to reconnect pds websocket after 5000 miniseconds');
            extr.m_connect = 1;
            $SC.startTimer(5000,0,0,"pdsreconnect",function(counter, gap, time) {
                if (!extr.m_connect) {
                    logmsg('no reconnect for m_connect', extr.m_connect);
                    $SC.stopTimer("","","pdsreconnect");
                    return;
                }
                if ($SC.agentState > 1) {
                    if (extr.websocket.readyState == 0) {
                        logmsg('try to reconnect now');
                        extr.connectpdsproxy();
                    } else {
                        logmsg('no reconnect for websocket.readyState = ' + extr.websocket.readyState.toString());
                    }
                } else {
                    logmsg('no reconnect for cti logout');
                }
            })
        }
    };

    extr.websocketsend = function(jsonobj, method, options) {
        logmsg("request", method, jsonobj);
        var request = JSON.stringify(jsonobj);
        extr.websocket.send(request);
    };

    extr.websocketclose = function() {
        try {
            if (extr.websocket) {
                logmsg("weboscket.close", extr.websocket.readyState);
                extr.websocket.close();
            }
        } catch (e) {
            logmsg("websocket.close with error", e.message, e.stack);
        }
    }

    extr.registeragent = function(campaignid) {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTREGSITER);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTREGSITER);
        addJsonStringValue(request, "agentid", $SC.agentId);
        addJsonStringValue(request, "extension", $SC.extension);
        addJsonStringValue(request, "campaignid", campaignid);
        extr.websocketsend(request, "registeragent");
    };

    extr.unregisteragent = function() {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTUNREGSITER);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTUNREGSITER);
        addJsonStringValue(request, "agentid", $SC.agentId);
        addJsonStringValue(request, "extension", $SC.extension);
        extr.websocketsend(request, "unregisteragent");
    };

    extr.reschedulecall = function(callid, reschedulephone, rescheduledate) {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTRESCHEDULECALL);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTRESCHEDULECALL);
        addJsonStringValue(request, "agentid", $SC.agentId);
        addJsonStringValue(request, "callid", callid);
        addJsonStringValue(request, "reschedulephone", reschedulephone);
        addJsonDateValue(request, "rescheduledate", rescheduledate);
        extr.websocketsend(request, "reschedulecall");
    };

    extr.agentacw = function() {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTACW);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTACW);
        addJsonStringValue(request, "agentid", $SC.agentId);
        extr.websocketsend(request, "agentacw");
    };

    extr.agentavailable = function() {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTAVAILABLE);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTAVAILABLE);
        addJsonStringValue(request, "agentid", $SC.agentId);
        extr.websocketsend(request, "agentavailable");
    };

    extr.agentbusy = function(obcallid) {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTBUSY);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTBUSY);
        addJsonStringValue(request, "agentid", $SC.agentId);
        addJsonStringValue(request, "callid", obcallid);
        extr.websocketsend(request, "agentbusy");
    };

    extr.agentcompletecall = function(callid, obresult, datas) {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTCOMPLETECALL);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTCOMPLETECALL);
        addJsonStringValue(request, "agentid", $SC.agentId);
        addJsonStringValue(request, "callid", callid);
        addJsonIntValue(request, "obresult", obresult);
        if (datas) {
            addJsonDatasValue(request, "datas", datas);
        }
        extr.websocketsend(request, "completeccall");
    };

    extr.agentotherwork = function() {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTOTHERWORK);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTOTHERWORK);
        addJsonStringValue(request, "agentid", $SC.agentId);
        extr.websocketsend(request, "agentotherwork");
    };

    extr.agentunavailable = function() {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTUNAVAILABLE);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTUNAVAILABLE);
        addJsonStringValue(request, "agentid", $SC.agentId);
        extr.websocketsend(request, "agentunavailable");
    };

    extr.donotcall = function(obcallid) {
        var request = {};
        addJsonIntValue(request, "event", PDSCONST.REQ_AGENTDONOTCALL);
        addJsonIntValue(request, "request", PDSCONST.REQ_AGENTDONOTCALL);
        addJsonStringValue(request, "agentid", $SC.agentId);
        addJsonStringValue(request, "callid", obcallid);
        extr.websocketsend(request, "donotcall");
    };

    extr.OnPDSEvent = function(event) {
        //$SC.addconsolelog('::ctiextra_elitepds, OnPDSEvent ' + event.data);
        logmsg("OnPDSEvent", event.data);
        var datas = eval('(' + event.data + ')');
        if (typeof datas.event) {
            var evt = parseInt(datas.event.value);
            switch (evt) {
                case PDSCONST.EVT_AGENTREGISTERSUCCESS:
                    extr.pdsstatus = "registered";
                    extr.campaignid = extr.campaignid0;
                    if ($SC.agentState == "2") {
                        extr.agentavailable();
                    } else if ($SC.agentState == "3" && $SC.agentMode == "3") {
                        extr.agentunavailable()
                    }
                    break;
                case PDSCONST.EVT_AGENTUNREGISTERSUCCESS:
                    extr.pdsstatus = "connected";
                    extr.campaignid = "";
                    extr.websocketclose();
                    break;
                case PDSCONST.PDS_EVT_DISCONNECTED:
                    extr.pdsstatus = "disconnected";
                    extr.campaignid = "";
                    break;
                case PDSCONST.PDS_EVT_CONNECTED:
                    extr.pdsstatus = "connected";
                    extr.registeragent(extr.campaignid0);
                    break;
            }
        //} else if (typeof datas.event != 'undefined') {
        //    var evt = parseInt(datas.event.value);
        //    if (evt == 12) {
                //此时才是真正连上了服务器，可以发送register请求
                //Extra.RegisterExtension($SC.dn);
        //    }
        }
    };

    function OnSCTIEvent(evt){
        var e = evt.toLowerCase();
        switch(e){
            case "72":
                if (extr.pdsstatus == "registered") {
                    extr.agentavailable();
                }
                break;
            case "73":
                if (extr.pdsstatus == "registered") {
                    if ($SC.agentMode == 4) {
                        extr.agentacw();
                    } else {
                        extr.agentunavailable();
                    }
                }
                break;
            case "oncallstart":
                extr.obcallid = "";
                if (extr.pdsstatus == "registered") {
                    if ($SC.CallInfo.AttachData("PDSType") == "E" ) {
                        var obcallid = $SC.CallInfo.AttachData("OBCallID");
                        if (obcallid) {
                            extr.obcallid = obcallid;
                            extr.agentbusy(obcallid);
                        }
                        if ($SC.autoAnswer == 1) {

                        } else {
                            $SC.answerCall();
                        }
                    } else {
                        extr.agentotherwork();
                    }
                }
                break;
            case "oncallestablish":
                if (extr.pdsstatus == "registered" && extr.obcallid) {
                    extr.agentbusy(extr.obcallid);
                }
                break;
            case "onlogin":
                if (extr.campaignid0) {
                    if (!extr.pdsstatus) {
                        extr.connectpdsproxy();
                    } else if (extr.pdsstatus == "connected") {
                        extr.registeragent(extr.campaignid0);
                    }
                }
                if (extr.m_connect) {
                    $SC.stopTimer("","","pdsreconnect");
                    extr.m_connect = 0;
                }
                break;
            case "onlogout":
                if (extr.campaignid) {
                    extr.unregisteragent();
                }
                if (extr.m_connect) {
                    $SC.stopTimer("","","pdsreconnect");
                    extr.m_connect = 0;
                }
                break;
        }
    }

    return Extra;
});